package com.xuwang.service.impl;

import com.auth0.jwt.interfaces.DecodedJWT;
import com.xuwang.Util.JWTutil;
import com.xuwang.pojo.Additive;
import com.xuwang.mapper.AdditiveMapper;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.springframework.stereotype.Service;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.*;

/**
 * 食品添加剂表(Additive)表服务实现类
 *
 * @author abaaba
 * @since 2021-09-13 18:35:48
 * @version 1.0
 */
@Service("additiveService")
public class AdditiveServiceImpl {
    @Resource
    private AdditiveMapper additiveMapper;


    /**
     * 导入
     */
    public Map<String, Object> importExcel(MultipartFile file, HttpServletRequest request, String abPath) throws IOException {

        Map<String, Object> map = new HashMap<>();
        String uploadPath = request.getServletContext().getRealPath("") + File.separator + abPath + File.separator;   // 得到相当项目工程的硬盘物理地址
        String fileName = file.getOriginalFilename();                   // 获取上传的文件名
        File newFile = new File(uploadPath + fileName);         // 根据当前工程的物理路径+文件名生成一个file对象
        System.out.println("newFile=" + newFile);
        FileCopyUtils.copy(file.getBytes(), newFile);                   // 通过上传通道中的字节码完成file文件的写入操作

        String path = newFile.toString();                                  // 获取文件的物理路径
        InputStream is = new FileInputStream(path);;                       // 生成输入流
        HSSFWorkbook workbook = new HSSFWorkbook(is);                      // HSSFWorkbook类型对应2003版本
        List<Additive> list = new ArrayList<>();
        Additive additive = null;
        Sheet sheet = workbook.getSheetAt(0);                       //模板数据默认读取第一个工作页sheet，index默认从0开始，如果存在多个sheet，那么需要循环Sheet判断

        for(int i = 2; i <= sheet.getLastRowNum(); i++) {
            Row row = sheet.getRow(i);
            additive = new Additive();
            Cell cell = row.getCell(0);
            cell.setCellType(Cell.CELL_TYPE_STRING);
            additive.setAdditiveName(cell.getStringCellValue());
            cell = row.getCell(1);
            cell.setCellType(Cell.CELL_TYPE_STRING);
            String trim = cell.getStringCellValue().trim();
//            System.out.println((cell.getStringCellValue()));
            additive.setSupplierId(additiveMapper.selectCompanyIdByCompanyName(trim));
            cell = row.getCell(2);
            cell.setCellType(Cell.CELL_TYPE_STRING);
            additive.setAdditiveWarranty(Integer.parseInt(cell.getStringCellValue()));
            list.add(additive);
        }
        System.out.println("用户上传的数据："+list.get(1).toString());
        additiveMapper.insertAll(list);
        map.put("code", 200);
        map.put("msg", "上传用户数据成功");
        return map;
    }



//    /**
//     * 查询所有数据
//     * @return  返回所有数据
//     */
//    public Map<String, Object> selectAll() {
//        Map<String, Object> map = new HashMap<>();
//        // 前端端分离时，前端人员会首先判断code值是否满足200，如果不是200，则提醒用户失败
//        map.put("code", 200);
//        map.put("msg", "查询成功");
//        map.put("data", this.additiveMapper.selectAll());
//        return map;
//    }

    /**
     * 通过ID查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    public Map<String, Object> selectById(String id) {
        Map<String, Object> map = new HashMap<>();
        // 前端端分离时，前端人员会首先判断code值是否满足200，如果不是200，则提醒用户失败
        map.put("code", 200);
        map.put("msg", "查询成功");
        map.put("data", this.additiveMapper.selectById(id));
        return map;
    }

    /**
     * 查询分页数据
     * @param additiveName      添加剂名
     * @param superCompanyName  供货商名
     * @param companyAddress    供货商地址
     * @param additiveWarranty  保质期
     * @return  返回数据
     */
    public Map<String, Object> selectForPage(int index,int page,String additiveName,String superCompanyName,String companyAddress,Integer additiveWarranty,String isDelete) {

        // 获取当前表中的总记录
        int tableCount = this.additiveMapper.selectForCount(additiveName,superCompanyName,companyAddress, additiveWarranty,isDelete);
        // 总页码计算   (总条数 - 1) / 每页显示条数  + 1
        // (100 - 1) / 10 + 1 = 10        (101 - 1) / 10 + 1 = 11      (99 - 1) / 10 + 1 = 10
        int pageCount = (tableCount - 1) / page + 1;
        // 计算每页开始的下标值
        index = (index - 1) * page;
        Map<String, Object> map = new HashMap<>();
        map.put("code", 0);   // 前端端分离时，前端人员会首先判断code值是否满足200，如果不是200，则提醒用户失败
        map.put("msg", "查询成功");
        map.put("pageCount", pageCount);  // 当前总数
        map.put("count", tableCount);     // 总条数
        map.put("data",  this.additiveMapper.selectForPage(index,page,additiveName,superCompanyName,companyAddress, additiveWarranty,isDelete));
        return map;

    }
    /**
     * 查询所有本公司的添加剂信息
     *
     * @return 实例对象
     */
    public Map<String, Object> selectAllTjjByToken(HttpServletRequest request) {

        String token = request.getHeader("Authorization");
        String userName = JWTutil.getUserName(token);

        Map<String, Object> map = new HashMap<>();
        map.put("code", 200);   // 前端端分离时，前端人员会首先判断code值是否满足200，如果不是200，则提醒用户失败
        map.put("msg", "查询成功");
//        map.put("data",this.additiveMapper.selectAll(this.additiveMapper.selectCompanyIdByUsername("添加剂人")));
        map.put("data",this.additiveMapper.selectAll(this.additiveMapper.selectCompanyIdByUsername(userName)));
//                this.additiveMapper.selectForPage(0,0,"",this.additiveMapper.selectCompanyNameByUsername("添加剂人"),"",0,"0"));
        return map;
    }
    /**
     * 新增数据
     *
     * @param additive 实例对象
     * @return 实例对象
     */
    public Map<String, Object> insert(Additive additive, HttpServletRequest request) {

        String token = request.getHeader("Authorization");
        String userName = JWTutil.getUserName(token);
        this.additiveMapper.insert(additive.getAdditiveName(),
//                this.additiveMapper.selectCompanyIdByUsername("添加剂人"),
                this.additiveMapper.selectCompanyIdByUsername(userName),
                additive.getAdditiveWarranty()
                );

        Map<String, Object> map = new HashMap<>();
        map.put("code", 200);   // 前端端分离时，前端人员会首先判断code值是否满足200，如果不是200，则提醒用户失败
        map.put("msg", "新增成功");
        return map;
    }

    /**
     * 通过ID查询单条数据
     *
     * @param additive 实例对象
     * @return 实例对象
     */
    public Map<String, Object> updateById(Additive additive, HttpServletRequest request) {
        String token = request.getHeader("Authorization");
        String userName = JWTutil.getUserName(token);

        additiveMapper.updateIsDeleteById(additive.getId().toString(),1);//删除更改前的数据
        this.additiveMapper.insert(additive.getAdditiveName(),
//                this.additiveMapper.selectCompanyIdByUsername("添加剂人"),
                this.additiveMapper.selectCompanyIdByUsername(userName),
                additive.getAdditiveWarranty()
        );
        Map<String, Object> map = new HashMap<>();
        map.put("code", 200);   // 前端端分离时，前端人员会首先判断code值是否满足200，如果不是200，则提醒用户失败
        map.put("msg", "更新成功");
        return map;
    }

    /**
     * 通过主键删除数据
     *
     * @param id 主键
     * @return 是否成功
     */
    public Map<String, Object> updateIsDeleteById(String id,int isDelete) {
        this.additiveMapper.updateIsDeleteById(id,isDelete);
        Map<String, Object> map = new HashMap<>();
        map.put("code", 200);   // 前端端分离时，前端人员会首先判断code值是否满足200，如果不是200，则提醒用户失败
        map.put("msg", isDelete==0?"恢复成功":"删除成功");
        return map;
    }

    /**
     * 批量删除多条数据
     *
     * @param ids 批量主键
     * @return 单条数据
     */
    public Map<String, Object> updateIsDeleteByIds(String ids) {
        String[] split = ids.split(",");
        for (int i = 0; i < split.length; i++) {
            this.additiveMapper.updateIsDeleteById(split[i],1);
        }
        Map<String, Object> map = new HashMap<>();
        map.put("code", 200);   // 前端端分离时，前端人员会首先判断code值是否满足200，如果不是200，则提醒用户失败
        map.put("msg", "删除多条成功");
        return map;
    }


    /**
     * 导出
     */
    public void exportExcel(String ids, HttpServletResponse response) throws IOException {
        String[] idArray = ids.split(",");
        System.out.println(ids);
        List<String> list = new ArrayList<>();
        list.addAll(Arrays.asList(idArray));
//        System.out.println("id list:---"+list);
        List<Additive> additiveList = additiveMapper.selectByIds(list);
//        System.out.println("additiveList:---"+additiveList.toString());

        HSSFWorkbook workbook = new HSSFWorkbook();
        HSSFSheet sheet = workbook.createSheet("添加剂表");

        Font f = workbook.createFont();                                // 创建字体
        f.setFontHeightInPoints((short) 10);                     // 创建字体样式：字体大小
        f.setColor(IndexedColors.BLACK.getIndex());              // 创建字体样式：字体类型(这里设置的是黑体)


        Font f2 = workbook.createFont();                                // 创建字体
        f2.setFontHeightInPoints((short) 10);                     // 创建字体样式：字体大小
        f2.setColor(IndexedColors.RED.getIndex());              // 创建字体样式：字体类型(这里设置的是黑体)
                                              // 创建字体样式：粗体

        CellStyle cs = workbook.createCellStyle();                     // 创建单元格每列格式对象
        cs.setFont(f);                                           // 把字体样式保存到样式单中


        CellStyle cs2 = workbook.createCellStyle();                     // 创建单元格每列格式对象
        cs2.setFont(f2);                                           // 把字体样式保存到样式单中


        Row row = sheet.createRow(0);                      // 在当前sheet页上创建一个新行
        createCell(0, "添加剂名称", cs2, sheet, row);
        createCell(1, "供货公司名", cs2, sheet, row);
        createCell(2, "添加剂保质期", cs2, sheet, row);
        createCell(3, "添加剂状态", cs2, sheet, row);

        for (int i = 0; i < additiveList.size(); i++) {                 // 设置每行每列的值  Row 行,Cell 方格 , Row 和 Cell 都是从0开始计数的
            row = sheet.createRow(i + 1);                      // 在当前sheet页上创建一个新行
            Additive additive = additiveList.get(i);
            createCell(0, additive.getAdditiveName(), cs, sheet, row);
            createCell(1, additive.getCompanyInfo().getCompanyName(), cs, sheet, row);
            createCell(2, String.valueOf(additive.getAdditiveWarranty()), cs, sheet, row);
            createCell(3, String.valueOf(additive.getIsDelete()==0? "未删除" : "已删除"), cs, sheet, row);
        }

        response.setCharacterEncoding("UTF-8");
        response.setHeader("Content-Disposition","attachment; filename=" + System.currentTimeMillis() + ".xls");
        //获取响应报文输出流对象
        ServletOutputStream out = response.getOutputStream();
        //输出
        workbook.write(out);
        out.flush();
        out.close();
    }

    public void createCell(int cellNum, String cellValue, CellStyle cs, Sheet sheet, Row row01) {
        sheet.setColumnWidth(cellNum, 256 * 35);            // 设置列宽。第一个参数表示要为第几列，第二个参数表示列的宽度，值为像素值。
        Cell cell01 = row01.createCell(cellNum);               // 在row行上创建一列
        cell01.setCellValue(cellValue);                        // 在此列上写入数据
        cell01.setCellStyle(cs);                              // 在此列上添加样式
    }

    public void downloadTemplate(HttpServletRequest request,HttpServletResponse response) throws IOException {
        //模拟文件，myfile.txt为需要下载的文件
        String fileName = request.getSession().getServletContext().getRealPath("")+File.separator +"downloadTemplate" +File.separator+"添加剂模板.xls";
        //获取输入流
        InputStream bis = new BufferedInputStream(new FileInputStream(new File(fileName)));
        fileName = URLEncoder.encode(fileName,"UTF-8");
        //设置文件下载头
        response.addHeader("Content-Disposition", "attachment;filename=" + fileName);
        //1.设置文件ContentType类型，这样设置，会自动判断下载文件类型
        response.setContentType("multipart/form-data");
        BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
        int len = 0;
        while((len = bis.read()) != -1){
            out.write(len);
            out.flush();
        }
        out.close();
    }
}